home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Cream of the Crop 1
/
Cream of the Crop 1.iso
/
PROGRAM
/
DDJ0992.ARJ
/
DBINT9.ASM
< prev
next >
Wrap
Assembly Source File
|
1992-06-10
|
29KB
|
1,341 lines
;dbint9.asm
;Keyboard ISR for debugger
;
.386P
;----------------------------------------------------------------------------
;Copyright 1991, 1992 ASMicro Co.
;3/1/92 Scott Schaefer and Rick Knoblaugh
;-----------------------------------------------------------------------------
;
;The code is table-driven, rather than the customary IF ... THEN ... ELSE type
;code typically seen. This makes the code somewhat faster for
;typical keys, and a lot faster for some.
;
;Of course, the standard tradeoff of size vs. speed causes it to
;be somewhat larger. It also has a couple of warts where some of
;the esoteric exceptions could not reasonably be handled according
;to the table-driven philosophy.
;
;Note that some of the key combinations which normally generate
;"internal" requests are not implemented (i.e. they are "dummied").
;Where these key combinations are recognized, the default action
;is commented-out, and a comment inserted which is enclosed in
;"<<< ... >>>" characters.
;
;Also, the INT 15, Keyboard Intercept (AH=4F) function is NOT called.
;
;Finally, the some BIOS docs state that their INT 9 "... places the
;value F0h in the low byte character code position for some
;Alt/character key combinations ...". This code does not do
;this -- since the standard INT 16 strips it anyway ....
;
;-----------------------------------------------------------------------------
include dbequ.inc
include dbstruc.inc
data segment para public 'data16' use16
extrn buf_put:word
extrn buf_get:word, key_buf:byte
BUF_START equ offset key_buf
BUF_END equ offset buf_put
data ends
;================
;In order to link with test program that simulates make/break codes,
;set this to some value; otherwise, leave it commented.
;================
;;LINK_CPP_TEST EQU 1
;================
;In order to run as real INT 9, but w/o debugger, set this to some
;value; otherwise, leave it commented.
;================
;;;;;STANDALONE_TEST EQU 1
;================
;I/O PORTS
;================
IO_KB_DATA EQU 60H
IO_KB_8042 EQU 64H
_8042_IBUF_FULL EQU 20H
IO_PIC EQU 20H
_EOI EQU 20H
;================
;8042 commands
;================
KB_8042_RESEND EQU 0FEH
KB_8042_ACK EQU 0FAH
KB_8042_DISABLE EQU 0ADH
KB_8042_ENABLE EQU 0AEH
KB_8042_NEWLED EQU 0EDH
KB_8042_CLR_REENABLE EQU 0F4H
DISABLE_KB MACRO
LOCAL KBOPEN
CALL WAIT_8042_ACCEPTED ;WAIT FOR OPEN LINE TO 8042
JNZ KBOPEN
MOV AL,KB_8042_DISABLE ;DISABLE INTERFACE
OUT IO_KB_8042,AL
STI
KBOPEN:
ENDM
ENABLE_KB MACRO
LOCAL KBOPEN
CALL WAIT_8042_ACCEPTED ;WAIT FOR OPEN LINE TO 8042
JNZ KBOPEN
MOV AL,KB_8042_ENABLE ;ENABLE INTERFACE
OUT IO_KB_8042,AL
STI
KBOPEN:
ENDM
;==============================
; BIOS DATA AREA VALUES
;==============================
BIOS_DATA SEGMENT use16 AT 40H
ORG 17H
BIOS_KB_SHIFT_FLAGS DB ?
BIOS_EXTKB_SHIFT_FLAGS DB ?
ORG 1AH
BIOS_KB_BUFPTR DW ?
BIOS_KB_BUFHEAD DW ?
BIOS_KB_BUFFER DW 16 DUP(?)
ORG 71H
BIOS_KB_CTRLBRK_FLAG DB ?
BIOS_KB_SOFTBOOT_FLAG DW ?
ORG 80H
BIOS_KB_EXTBUFHEAD DW ?
BIOS_KB_EXTBUFEND DW ?
ORG 96H
BIOS_KB_EXTSTAT_1 DB ?
BIOS_KB_EXTSTAT_2 DB ?
BIOS_DATA ENDS
;
;================
;Bits in BIOS_KB_SHIFT_FLAGS
;================
INS_ACTIVE EQU 80H
CAPSLK_ACTIVE EQU 40H
NUMLK_ACTIVE EQU 20H
SCRLK_ACTIVE EQU 10H
ALT_PRESSED EQU 8
CTRL_PRESSED EQU 4
LSHIFT_PRESSED EQU 2
RSHIFT_PRESSED EQU 1
;================
;Bits in BIOS_EXTKB_SHIFT_FLAGS
;================
INS_PRESSED EQU 80H
CAPSLK_PRESSED EQU 40H
NUMLK_PRESSED EQU 20H
SCRLK_PRESSED EQU 10H
PAUSE_ACTIVE EQU 8
SYSREQ_PRESSED EQU 4
LALT_PRESSED EQU 2
LCTRL_PRESSED EQU 1
;================
;Bits in BIOS_KB_EXTSTAT_1
;================
READID_INPROG EQU 80H
LASTCODE_ID1 EQU 40H
NUMLK_FORCED EQU 20H
EXT_KEYBOARD EQU 10H
RALT_ACTIVE EQU 8
RCTRL_ACTIVE EQU 4
LASTCODE_E0 EQU 2
LASTCODE_E1 EQU 1
;================
;Bits in BIOS_KB_EXTSTAT_2
;================
ERRFLAG_KBCMD EQU 80H
LEDUPD_INPROG EQU 40H
RESEND_FROM8042 EQU 20H
ACK_FROM8042 EQU 10H
; EQU 8
CAPSLK_LED EQU 4
NUMLK_LED EQU 2
SCRLK_LED EQU 1
;
;================
;Values used by the ISR
;================
BREAK_CODE EQU 80H
CTRL_PRSTC EQU 7200H ;SPECIAL SCAN CODE FOR START/STOP PRINT
;-------------------
; Handler types
;-------------------
NORM EQU 1
NORM_CA0 EQU 2
FNKEY EQU 3
NUMPAD EQU 4
SPACEKEY EQU 5
SLASHKEY EQU 6
SYSKEY EQU 7
PRTSCKEY EQU 8
TOGGLEKEY EQU 9
SHIFTKEY EQU 10
TWOPART EQU 11
ACK_RXCODE EQU 12
RESEND_RXCODE EQU 13
OVERRUN_RXCODE EQU 14
EXITS_PAUSE EQU TOGGLEKEY ;KEYS < THIS, ALWAYS EXIT PAUSE STATE
CTRL_INVALID EQU 0FFH ;WHEN <CTRL>-KEY IS INVALID
BEEP_NOCODE EQU 0FCH
NOCODE_PICRESET EQU 0FDH
NEW_PAUSE_RQ EQU 0FEH
STORE_NOCODE EQU 0FFH
;
IFDEF LINK_CPP_TEST
_TEXT SEGMENT BYTE PUBLIC 'CODE' use16
ASSUME CS:_TEXT
PUBLIC _lastkey
PUBLIC _int9_test_entry
KBBUF DW 0
_lastkey:
MOV AX,CS:KBBUF
RET
_int9_test_entry:
MOV CS:KBBUF,0
JMP NEAR PTR KB_ISR
ELSE
IFDEF STANDALONE_TEST
_TEXT SEGMENT BYTE PUBLIC 'CODE' use16
ASSUME CS:_TEXT
ELSE
zcode segment para public 'code16' use16
public int_9_isr
ENDIF
ENDIF
ASSUME CS:zcode, DS:NOTHING, ES:NOTHING, SS:NOTHING
;---------------------------
;"handler()" vectors
;
;This table MUST be in order according
;to the 'Handler types' equates above
;---------------------------
JUMP_TAB LABEL WORD
DW NORM_HANDLER
DW TAB_HANDLER
DW FNKEY_HANDLER
DW NUMPAD_HANDLER
DW SPACE_HANDLER
DW SLASH_HANDLER
DW SYS_HANDLER
DW PRTSC_HANDLER
DW TOGGLEKEY_HANDLER
DW SHIFTKEY_HANDLER
DW TWOPART_HANDLER
DW ACK_HANDLER
DW RESEND_HANDLER
DW OVERRUN_HANDLER
;---------------------------
;Which translate table to use based upon shift state is determined
;by this array. 'BIOS_KB_SHIFT_FLAGS' word is manipulated to produce:
; Bit 0:Shift
; Bit 1:Ctrl
; Bit 2:Alt
;The result, 0-7 is used to index the table.
;
;Note tha values prioritize simultaneous multiple shift states as:
; Highest: Alt
; Middle: Ctrl
; Lowest: Shift
;---------------------------
SHIFT_TABLES LABEL WORD
DW OFFSET UNSHIFTED_XLAT_TAB ;NO SHIFTS
DW OFFSET SHIFTED_XLAT_TAB ;EITHER SHIFT = 1
DW OFFSET CTRL_XLAT_TAB ;CTRL
DW OFFSET CTRL_XLAT_TAB ;CTRL+SHIFT (CTRL > PRIORITY)
DW OFFSET ALT_XLAT_TAB ;ALT HIGHEST PRIORITY OF ALL
DW OFFSET ALT_XLAT_TAB
DW OFFSET ALT_XLAT_TAB
DW OFFSET ALT_XLAT_TAB
;---------------------------
;Each of the next five tables is indexed via scan code.
;
;This first table returns an index into the JUMP_TAB table to
;vector to the proper key-handler.
;
;Note that this table is index via raw scan code; almost all values > 127
;return 0 since these are "break" codes.
;---------------------------
JUMPTAB_INDEX DB OVERRUN_RXCODE ;OVERRUN SCANCODE (SOME DOCS)
DB NORM ;<Esc>
DB 12 DUP(NORM) ;"1!" through "=+"
DB NORM ;<BS>
DB NORM_CA0 ;<TAB>
DB 12 DUP(NORM) ;"Q" through "]"
DB NORM ;<Enter>
DB SHIFTKEY
DB 9 DUP(NORM) ;"A" through "L"
DB 3 DUP(NORM) ;";:", "'"", and "`~"
DB SHIFTKEY
DB NORM ;"\|"
DB 7 DUP(NORM) ;"Z" through "M"
DB 2 DUP(NORM) ;",<", ".>"
DB SLASHKEY ;"/?", KEYPAD SLASH IF E0
DB SHIFTKEY
DB PRTSCKEY ;E0-PRTSC, ELSE ASTERISK JUST LIKE TAB
DB SHIFTKEY
DB SPACEKEY ;SPACE BAR
DB TOGGLEKEY ;CAPSLOCK
DB 10 DUP(FNKEY) ;F1-F10
DB TOGGLEKEY ;NUMLOCK
DB TOGGLEKEY ;SCROLLOCK
DB 3 DUP(NUMPAD)
DB NORM_CA0 ;KEYPAD -
DB 3 DUP(NUMPAD)
DB NORM_CA0 ;KEYPAD +
DB 5 DUP(NUMPAD)
DB SYSKEY ;SCAN CODE 54H
DB 0 ;SCAN CODE 55H
DB NORM
DB 2 DUP(FNKEY) ;F11-F12
DB 80H - ($ - JUMPTAB_INDEX) DUP(0)
;BREAK KEYS START HERE
DB 29 DUP(0)
DB SHIFTKEY
DB 12 DUP(0)
DB SHIFTKEY
DB 11 DUP(0)
DB SHIFTKEY
DB 0
DB SHIFTKEY
DB 0
DB TOGGLEKEY ;CAPSLOCK
DB 10 DUP(0)
DB TOGGLEKEY ;NUMLOCK
DB TOGGLEKEY ;SCROLLOCK
DB 0E0H - ($ - JUMPTAB_INDEX) DUP(0)
DB TWOPART
DB TWOPART
DB KB_8042_ACK - ($ - JUMPTAB_INDEX) DUP(0)
DB ACK_RXCODE
DB 0,0,0
DB RESEND_RXCODE
DB OVERRUN_RXCODE ;OVERRUN SCANCODE (SOME OTHER DOCS)
;
;---------------------------
;The remaining four tables comprise the translate tables.
;Note each of these tables need only contain entries for codes
;which we actually translate; since the only break codes we care
;about (non-zero entires in JUMPTAB_INDEX) don't get translated,
;these tables need only have entries for codes 0-58H.
;---------------------------
UNSHIFTED_XLAT_TAB LABEL BYTE
DB 0
DB 1BH
DB "1234567890-="
DB 8,9 ;BS, TAB
DB "qwertyuiop[]"
DB 0DH ;ENTER
DB CTRL_PRESSED ;<CTRL>
DB "asdfghjkl;"
DB 39 ;SINGLE QUOTE
DB "`"
DB LSHIFT_PRESSED ;LEFT <SHIFT>
DB 5CH
DB "zxcvbnm,./"
DB RSHIFT_PRESSED ;RIGHT <SHIFT>
DB "*"
DB ALT_PRESSED ;<ALT>
DB " " ;SPACE BAR
DB CAPSLK_PRESSED ;CAPSLOCK
DB 10 DUP(0) ;UNSHIFTED FN KEY ( += SCAN CODE)
DB NUMLK_PRESSED ;NUMLOCK
DB SCRLK_PRESSED ;SCROLLOCK
DB 47H,48H,49H
DB "-"
DB 4BH,4CH,4DH
DB "+"
DB 4FH,50H,51H,52H,53H
DB 0,0 ;SCAN CODE 54H, 55H
DB 5CH
DB 2 DUP(85H-57H) ;UNSHIFTED F11-F12 ( += SCAN CODE)
;
SHIFTED_XLAT_TAB LABEL BYTE
DB 0
DB 1BH
DB "!@#$%^&*()_+"
DB 8 ;BS
DB 0 ;SHIFT-TAB GETS 0 IN LOW BYTE
DB "QWERTYUIOP{}"
DB 0DH ;ENTER
DB CTRL_PRESSED ;<CTRL>
DB "ASDFGHJKL:"
DB 34 ;DOUBLE QUOTE
DB "~"
DB LSHIFT_PRESSED ;LEFT <SHIFT>
DB 7CH
DB "ZXCVBNM<>?"
DB RSHIFT_PRESSED ;RIGHT <SHIFT>
DB "*"
DB ALT_PRESSED ;<ALT>
DB " " ;SPACE BAR
DB CAPSLK_PRESSED ;CAPSLOCK
DB 10 DUP(54H-3BH) ;SHIFTED FN KEY ( += SCAN CODE )
DB NUMLK_PRESSED ;NUMLOCK
DB SCRLK_PRESSED ;SCROLLOCK
DB "789" ;NUMPAD ENTRIES
DB "-"
DB "456" ;NUMPAD ENTRIES
DB "+"
DB "1230." ;NUMPAD ENTRIES
DB 0,0 ;SCAN CODE 54H, 55H
DB 7CH
DB 2 DUP(87H-57H) ;SHIFTED F11-F12 ( += SCAN CODE)
;
CTRL_XLAT_TAB LABEL BYTE
DB 0
DB 1BH ;CTRL-ESC STILL 1B IN LOW BYTE
DB CTRL_INVALID ;CTRL-1 INVALID
DB 0 ;CTRL-2 GETS 0 IN LOW BYTE
DB CTRL_INVALID ;CTRL-3/4/5 INVALID
DB 2 DUP(CTRL_INVALID)
DB 1EH ;CTRL-6 GETS 1EH IN LOW BYTE
DB CTRL_INVALID ;CTRL-7/8/9/0 INVALID
DB 3 DUP(CTRL_INVALID)
DB 1FH ;CTRL-DASH GETS 1EH IN LOW BYTE
DB CTRL_INVALID ;CTRL-EQUALS INVALID
DB 7FH ;CTRL-BS IS TREATED AS ASCII DEL
DB 94H ;CTRL-TAB
DB 'Q' - 'A' + 1
DB 'W' - 'A' + 1
DB 'E' - 'A' + 1
DB 'R' - 'A' + 1
DB 'T' - 'A' + 1
DB 'Y' - 'A' + 1
DB 'U' - 'A' + 1
DB 'I' - 'A' + 1
DB 'O' - 'A' + 1
DB 'P' - 'A' + 1
DB 1BH, 1DH
DB 0AH ;CTRL-ENTER TREATED AS ASCII LF
DB CTRL_PRESSED ;<CTRL>
DB 'A' - 'A' + 1
DB 'S' - 'A' + 1
DB 'D' - 'A' + 1
DB 'F' - 'A' + 1
DB 'G' - 'A' + 1
DB 'H' - 'A' + 1
DB 'J' - 'A' + 1
DB 'K' - 'A' + 1
DB 'L' - 'A' + 1
DB 3 DUP(CTRL_INVALID) ;CTRL-";","'", AND "`" INVALID
DB LSHIFT_PRESSED ;LEFT <SHIFT>
DB 1CH
DB 'Z' - 'A' + 1
DB 'X' - 'A' + 1
DB 'C' - 'A' + 1
DB 'V' - 'A' + 1
DB 'B' - 'A' + 1
DB 'N' - 'A' + 1
DB 'M' - 'A' + 1
DB 3 DUP(CTRL_INVALID) ;CTRL-",",".", AND "/" INVALID
DB RSHIFT_PRESSED ;RIGHT <SHIFT>
DB 96H ;CTRL-*
DB ALT_PRESSED ;<ALT>
DB " " ;CTRL-SPACE TREATED IN HANDLER
DB CAPSLK_PRESSED ;CAPSLOCK
DB 10 DUP(5EH-3BH) ;CTRL-FN KEY ( += SCAN CODE )
DB PAUSE_ACTIVE ;NUMLOCK
DB SCRLK_PRESSED ;SCROLLOCK
DB 77H ;NUMPAD ENTRIES
DB 8DH
DB 84H
DB 8EH ; -
DB 73H
DB 8FH
DB 74H
DB 90H ; +
DB 75H
DB 91H
DB 76H
DB 92H
DB 93H
DB 0,0 ;SCAN CODE 54H, 55H
DB CTRL_INVALID
DB 2 DUP(89H-57H) ;<CTRL> F11-F12 ( += SCAN CODE)
;
ALT_XLAT_TAB LABEL BYTE
DB 0
DB 1
DB 78H,79H,7AH,7BH,7CH,7DH,7EH,7FH
DB 80H,81H,82H,83H
DB 0EH
DB 0A5H ;ALT-TAB
DB 10H,11H,12H,13H,14H,15H,16H,17H
DB 18H,19H,1AH,1BH,1CH
DB CTRL_PRESSED ;<CTRL>
DB 1EH,1FH
DB 20H,21H,22H,23H,24H,25H,26H,27H
DB 28H,29H
DB LSHIFT_PRESSED ;LEFT <SHIFT>
DB 2BH,2CH,2DH,2EH,2FH
DB 30H,31H,32H,33H,34H,35H
DB RSHIFT_PRESSED ;RIGHT <SHIFT>
DB 37H ;ALT-*
DB ALT_PRESSED ;<ALT>
DB " " ;ALT-SPACE BAR TREATED IN HANDLER
DB CAPSLK_PRESSED ;CAPSLOCK
DB 10 DUP(68H-3BH) ;ALT-FN KEY ( += SCAN CODE )
DB PAUSE_ACTIVE ;NUMLOCK
DB SCRLK_PRESSED ;SCROLLOCK
DB 97H,98H,99H ;SEPARATE KEYS (E0 SCAN)
DB 4AH ; -
DB 9BH
DB 0 ;NO SEPARATE KEY FOR <5>
DB 9DH
DB 4EH ; +
DB 9FH,0A0H,0A1H,0A2H,0A3H
DB 0,0 ;SCAN CODE 54H, 55H
DB CTRL_INVALID
DB 2 DUP(8BH-57H) ;<ALT> F11-F12 ( += SCAN CODE)
ALTBYTE DB 0 ;BUILDING VALUE WITH <ALT>-KEYPAD
;
int_9_isr PROC FAR
;--------------------------------------
;Entry point of the ISR
;--------------------------------------
int_9_100:
STI
PUSH AX
PUSH BX
PUSH CX
PUSH SI
PUSH DS
IFDEF LINK_CPP_TEST ;Linkage different during test
MOV CX,CS ;since AL has "simulated" scan code
MOV DS,CX ;can't lose it by using AX !!
ASSUME DS:_TEXT
MOV CX,BIOS_DATA
MOV DS,CX
ASSUME DS:BIOS_DATA
MOV AH,CH ;we also rely on AH=0 from MOV AX,BIOS_DATA
ELSE
MOV AX,CS
MOV DS,AX
IFDEF STANDALONE_TEST
ASSUME DS:_TEXT
ELSE
ASSUME DS:zcode
ENDIF
DISABLE_KB
CALL WAIT_8042_ACCEPTED ;MUST WAIT FOR THIS TO BE ACCEPTED
STI
MOV AX,BIOS_DATA
MOV DS,AX
ASSUME DS:BIOS_DATA
IN AL,IO_KB_DATA ;READ THE SCAN CODE
ENDIF
MOV BL,AL ;SCAN CODE TO BL FOR INDEX
MOV BH,AH ;AH STILL 0 FROM BIOS_DATA
MOV AH,AL ;DUPLICATE SCAN CODE IN AH
AND AL,NOT BREAK_CODE
MOV BL,CS:JUMPTAB_INDEX [BX]
DEC BX ;ENTRY WAS 0 ??
JS IGNORE_NOBEEP ;SCAN CODE IS TOTALLY IGNORED
TEST BIOS_EXTKB_SHIFT_FLAGS,PAUSE_ACTIVE
JZ NOPAUSE ;NOT IN PAUSE STATE
TEST AH,BREAK_CODE
JNZ NOPAUSE ;CAN'T EXIT ON BREAK KEY
CMP BL,EXITS_PAUSE
JNL NOPAUSE ;KEY DOES NOT EXIT PAUSE STATE
AND BIOS_EXTKB_SHIFT_FLAGS,NOT PAUSE_ACTIVE
JMP SHORT IGNORE_NOBEEP
NOPAUSE:
MOV CL,BIOS_KB_SHIFT_FLAGS ;GET CURRENT SHIFT FLAGS
MOV SI,CX
AND SI,15 ;ISOLATE SHIFTS AND CY=0
RCR SI,1
JNC NO_RIGHTSH
OR SI,1 ;RIGHT SHIFT WAS ON
NO_RIGHTSH:
SHL SI,1
MOV SI,CS:SHIFT_TABLES [SI]
SHL BX,1
XCHG SI,BX
CALL CS:JUMP_TAB [SI]
CMP AH,BEEP_NOCODE
JAE IGNORE_SCANCODE
CMP AL,CTRL_INVALID
JE IGNORE_SCANCODE
;Have word to insert in buffer here....
MOV CS:ALTBYTE,0
AND BIOS_KB_EXTSTAT_1,NOT (LASTCODE_E0 OR LASTCODE_E1)
IFDEF LINK_CPP_TEST
MOV CS:KBBUF,AX ;STORE TO LOCAL WORD
ENDIF
IFDEF STANDALONE_TEST
MOV CX,AX ;OR STORE TO BUFFER FOR INT 16 GET
MOV AH,5
INT 16H
ENDIF
; Store to debugger buffer
push ds
mov bx, DATA
mov ds, bx
ASSUME DS:DATA
mov bx, buf_put ;get buffer ptr
mov si, bx
add bx, 2 ;advance to next position
cmp bx, BUF_END ;at end?
jne short int_9_i200
mov bx, BUF_START ;if so, wrap
int_9_i200:
cmp bx, buf_put ;buffer full?
je short int_9_900 ;if so, don't store char
mov [si], ax ;store ascii char and scan
mov buf_put, bx ;save buffer pointer
int_9_900:
pop ds
ASSUME DS:BIOS_DATA
JMP SHORT RESET_PIC_REENABLE_KB
IGNORE_SCANCODE:
JNE IGNORE_NOBEEP
;If you want a beep, it goes here
IGNORE_NOBEEP:
CMP AH,NOCODE_PICRESET
JE PIC_RESET_OK
RESET_PIC_REENABLE_KB:
IFNDEF LINK_CPP_TEST
MOV AL,_EOI
OUT IO_PIC,AL
ENDIF
PIC_RESET_OK:
IFNDEF LINK_CPP_TEST
ENABLE_KB
ENDIF
CMP AH,NEW_PAUSE_RQ
JNE ISR_DONE
MOV AL,PAUSE_ACTIVE
OR BIOS_EXTKB_SHIFT_FLAGS,AL
STI
ISPC: ;Incredibly Stupid Pause Code
TEST BIOS_EXTKB_SHIFT_FLAGS,AL
JNZ ISPC
ISR_DONE:
POP DS
POP SI
POP CX
POP BX
POP AX
IRET
int_9_isr ENDP
;
;=================================================
;Each of these functions is called with:
; AH = Original scancode
; AL = Scancode with bit 7 = 0
; CL = BIOS_KB_SHIFT_FLAGS
; CS:BX --> Translate table based on shift status
; DS = BIOS_DATA segment
;
;Each returns:
; AX = Word to be added to keyboard buffer, UNLESS:
; AH=BEEP_NOCODE
; AH=NOCODE_PICRESET (PIC reset by handler also !)
; AH=NEW_PAUSE_RQ
; AH=STORE_NOCODE, OR
; AL=CTRL_INVALID
;=================================================
NORM_HANDLER PROC NEAR
;---------------------------------------
;Would be dead-nuts simple except for stupid CAPSLOCK problem.
;
;Translated code goes to AL, scan code stays in AH
;---------------------------------------
TEST CL,ALT_PRESSED
JNZ XLATHI_ZEROLOW
NORM_HANDLER_NOATL:
XLAT CS:[BX]
TEST CL,CAPSLK_ACTIVE
JZ CASE_OK
TEST CL,(LSHIFT_PRESSED OR RSHIFT_PRESSED)
MOV CX,("A" SHL 8) OR "Z" ;ASSUME XLATE UPPER TO LOWER
JNZ CHECK_RECASE ;WHAT TO DO WHEN EITHER SHIFT DOWN
MOV CX,("a" SHL 8) OR "z" ;ELSE XLATE LOWER TO UPPER
CHECK_RECASE:
CMP AL,CH ;CHECK FOR IN RANGE THAT REQUIRES XLATE
JB CASE_OK
CMP AL,CL
JA CASE_OK
XOR AL,"a"-"A" ;TOGGLE IT THE OTHER WAY
CASE_OK:
RET
NORM_HANDLER ENDP
SPACE_HANDLER PROC NEAR
;---------------------------------------
;SpaceBar always returns 3920, irregardless of shift state
;---------------------------------------
MOV AX,3920H
RET
SPACE_HANDLER ENDP
SLASH_HANDLER PROC NEAR
;---------------------------------------
;Differences between slash on "/?" key and numpad "/"
;---------------------------------------
TEST BIOS_KB_EXTSTAT_1,LASTCODE_E0
JZ NORM_HANDLER
MOV AX,0E02FH
TEST CL,(ALT_PRESSED OR CTRL_PRESSED)
JZ KEYPAD_SLASHRET
MOV AX,9500H
TEST CL,CTRL_PRESSED
JNZ KEYPAD_SLASHRET
ADD AH,0A4H - 95H
KEYPAD_SLASHRET:
RET
SLASH_HANDLER ENDP
PRTSC_HANDLER PROC NEAR
;---------------------------------------
;---------------------------------------
TEST BIOS_KB_EXTSTAT_1,LASTCODE_E0
JNZ PRTSC_KEYPRESS
;Since not PrtSc, check for clear Pause state
TEST BIOS_EXTKB_SHIFT_FLAGS,PAUSE_ACTIVE
JZ TAB_HANDLER
AND BIOS_EXTKB_SHIFT_FLAGS,NOT PAUSE_ACTIVE
JMP SHORT PRTSC_NOCODE
PRTSC_KEYPRESS:
MOV AX,CTRL_PRSTC
TEST CL,CTRL_PRESSED
JNZ PRTSC_RET
;<<<< PRTSC HERE >>>>
;;; INT 5
PRTSC_NOCODE:
MOV AH,STORE_NOCODE
PRTSC_RET:
RET
PRTSC_HANDLER ENDP
TAB_HANDLER PROC NEAR
;---------------------------------------
;All except Ctrl-xx versions are just like normal keys.
;
;For Ctrl, table contains the value which is to be placed in
;the high byte; 0 is placed in the low byte (like NORM <Alt>).
;
;Codes vectored here include: TAB, keypad *-+
;---------------------------------------
TEST CL,(ALT_PRESSED OR CTRL_PRESSED)
JNZ XLATHI_ZEROLOW
XLAT_RET: ;CAN JUMP HERE FOR SIMPLE XLAT AND RET
XLAT CS:[BX]
RET
XLATHI_ZEROLOW: ;JUMP HERE WHEN TABLE HAS HI BYTE, LOW BYTE TO = 0
XOR AH,AH
XLATHI_E0LOW: ;JUMP HERE WHEN TABLE HAS HI BYTE, AL=LOW BYTE
XLAT CS:[BX]
XCHG AH,AL
RET
TAB_HANDLER ENDP
FNKEY_HANDLER PROC NEAR
;---------------------------------------
;For function keys, the table contains the value which is to be
;ADDED to the scan code.
;
;Key result is a zero in low byte; translated scancode in high byte
;---------------------------------------
XLAT CS:[BX]
ADD AH,AL
XOR AL,AL
RET
FNKEY_HANDLER ENDP
NUMPAD_HANDLER PROC NEAR
;---------------------------------------
;The numeric keypad handling gets a little tricky ...
;
;For Ctrl and Alt, the tables contain the value which is
;to be placed in the high byte; a 00 OR E0 is placed in the low byte.
;
;This routine DOES NOT update the INS_ACTIVE and INS_PRESSED flags !!
;---------------------------------------
MOV CH,BIOS_KB_EXTSTAT_1
TEST CL,ALT_PRESSED ;TEST ALT PRESSED
JNZ ALT_NUMPAD_ENTRY ;ALT ENTRIES ARE DIFFERENT
;NOT <ALT> ...
TEST CH,LASTCODE_E0 ;SEPARATE SET OF CURSOR KEYS ??
JZ DUAL_NUMPAD_KEY ;NO -- ONE OF OLD DUAL/KEYS
MOV AH,0E0H
CMP BX,OFFSET SHIFTED_XLAT_TAB ;<SHIFT> TABLE WILL GIVE US 0-9 !
JNZ XLATHI_E0LOW ;IT'S OK -- BX HAS CORRECT TABLE
MOV BX,OFFSET UNSHIFTED_XLAT_TAB
JMP XLATHI_E0LOW
DUAL_NUMPAD_KEY:
TEST CL,CTRL_PRESSED
JNZ XLATHI_ZEROLOW ;THESE ALL GET ZERO IN LOW BYTE
MOV BX,OFFSET SHIFTED_XLAT_TAB
XLAT CS:[BX]
MOV SI,AX ;SI IS VALUE IF "SHIFTED"
XOR AL,AL ;AX IS VALUE IF NOT
TEST CL,NUMLK_ACTIVE
JZ NUMPAD_TOGOFF
XCHG AX,SI ;REVERSE WHEN NUMLOCK ACTIVE
NUMPAD_TOGOFF:
TEST CL,(LSHIFT_PRESSED OR RSHIFT_PRESSED)
JZ NUMPAD_SHIFTNORM
MOV AX,SI
NUMPAD_SHIFTNORM:
RET
ALT_NUMPAD_ENTRY:
CMP AH,53H ;DELETE KEY MAKE ??
JNZ NO_REBOOT
TEST CL,CTRL_PRESSED ;CTRL PRESSED ALSO ??
JZ NO_REBOOT
;<<<< CTRL-ALT-DELETE HERE >>>>
MOV AH,STORE_NOCODE
RET
NO_REBOOT:
TEST CH,LASTCODE_E0 ;SEPARATE SET OF CURSOR KEYS ??
JNZ XLATHI_ZEROLOW ;THESE GET ZERO IN LOW BYTE
MOV AH,STORE_NOCODE ;RETURN CODE
MOV BX,OFFSET SHIFTED_XLAT_TAB ;XLAT TO 0-9
XLAT CS:[BX]
SUB AL,"0"
JC NUMPAD_NODIGIT
CMP AL,9
JA NUMPAD_NODIGIT
XCHG AH,CS:ALTBYTE
SHL AH,1
ADD AL,AH ;ORIGINAL * 2 + NEW
SHL AH,2 ;ORIGINAL * 8
ADD AH,AL
XCHG CS:ALTBYTE,AH ;STORE NEW VALUE, GET BACK RETURN CODE
NUMPAD_NODIGIT:
RET
NUMPAD_HANDLER ENDP
TWOPART_HANDLER PROC NEAR
;---------------------------------------
;Vectored here because scan code was E0 or E1.
;
;Set proper bits in 'BIOS_KB_EXTSTAT_1'
;
;Return STORE_NOCODE so bogus code not saved to buffer.
;---------------------------------------
MOV AL,LASTCODE_E1
CMP AH,0E1H
JZ SET_LASTCODE_FLAG
MOV AL,LASTCODE_E0
SET_LASTCODE_FLAG:
OR BIOS_KB_EXTSTAT_1,AL ;TURN ON LAST CODE FLAG
XOR AL,3
NOT AL
AND BIOS_KB_EXTSTAT_1,AL ;TURN OFF OPPOSITE ONE
MOV AH,STORE_NOCODE
RET
TWOPART_HANDLER ENDP
TOGGLEKEY_HANDLER PROC NEAR
;---------------------------------------
;The toggle keys require setting/clearing bits, and perhaps
;updating the keyboard LED indicators.
;
;The three keys which vector here are: CAPSLOCK, NUMLOCK, SCROLL-LOCK
;---------------------------------------
TEST BIOS_EXTKB_SHIFT_FLAGS,PAUSE_ACTIVE
JZ TOGGLE_NO_PAUSE
CMP AL,45
JZ TOGGLE_NO_PAUSE ;CAN'T EXIT PAUSE W/NUM LOCK KEY
TEST CL,CTRL_PRESSED
JZ TOGGLE_NO_PAUSE ;ONLY CTRL-TOGGLE EXITS PAUSE
AND BIOS_EXTKB_SHIFT_FLAGS,NOT PAUSE_ACTIVE
MOV AH,STORE_NOCODE
RET
TOGGLE_NO_PAUSE:
XLAT CS:[BX] ;BITS FOR BIOS_KB_SHIFT_FLAGS
CMP AL,PAUSE_ACTIVE
JNE NO_TOGGLE_PAUSE
;PAUSE REQUEST HERE
TEST CL,AL ;ALREADY PAUSE ???
JNZ NEW_SHIFT_STATE2 ;C'MON ...
AND BIOS_KB_EXTSTAT_1,NOT (LASTCODE_E0 OR LASTCODE_E1)
MOV AH,NEW_PAUSE_RQ
RET
NO_TOGGLE_PAUSE:
TEST AH,BREAK_CODE
JNZ TOGGLE_BREAK
CMP AH,46H ;SCROLL-LOCK KEY MAKE ??
JNZ NO_CTRLBREAK
TEST CL,CTRL_PRESSED ;CTRL PRESSED ALSO ??
JZ NO_CTRLBREAK
;<<<< CTRL-BREAK HERE >>>>
;; INT 1BH
MOV AH,STORE_NOCODE
RET
NO_CTRLBREAK:
OR BIOS_EXTKB_SHIFT_FLAGS,AL ;MARK IT'S PRESSED
XOR CL,AL ;TOGGLE STATE ON MAKE ONLY
MOV BIOS_KB_SHIFT_FLAGS,CL ;SAVE NEW STATE
IFNDEF LINK_CPP_TEST
MOV AL,_EOI
OUT IO_PIC,AL
ENDIF
CALL NEW_LEDS
AND BIOS_KB_EXTSTAT_1,NOT (LASTCODE_E0 OR LASTCODE_E1)
MOV AH,NOCODE_PICRESET
RET
TOGGLE_BREAK:
NOT AL
AND BIOS_EXTKB_SHIFT_FLAGS,AL ;MARK NO LONGER PRESSED
JMP SHORT NEW_SHIFT_STATE
TOGGLEKEY_HANDLER ENDP
SHIFTKEY_HANDLER PROC NEAR
;---------------------------------------
;The shift keys require setting/clearing bits.
;
;When <Alt> key is released, have to check for accumed ASCII
;value entered via numeric keypad.
;
;There are actually six keys which vector here:
; Left/Right CTRL, Left/Right ALT, and Left/Right SHIFT
;---------------------------------------
XLAT CS:[BX] ;BITS FOR BIOS_KB_SHIFT_FLAGS
XOR CH,CH
TEST BIOS_KB_EXTSTAT_1,LASTCODE_E0
JZ SHIFT_MASKS_SET ;LAST NOT E0, IF CTRL/ALT, WAS RIGHT KEY
CMP AL,CTRL_PRESSED
JZ SHIFT_ISCTRL
CMP AL,ALT_PRESSED
JZ SHIFT_MASKS_SET ;WAS L/R SHIFT, CH=0
INC CH ;LALT_PRESSED = 2
SHIFT_ISCTRL:
INC CH ;LCTRL_PRESSED = 1
SHIFT_MASKS_SET:
TEST AH,BREAK_CODE
JZ SHIFTMAKE
;Shift key released here ...
CMP AL,ALT_PRESSED
PUSHF
NOT AL
AND CL,AL
NOT CH
AND BIOS_EXTKB_SHIFT_FLAGS,CH
CALL SHORT NEW_SHIFT_STATE
POPF
JNZ SHIFTBRK_NONALT
XOR AX,AX
XCHG AL,CS:ALTBYTE
CMP AH,AL ;AH=0, AL=Byte accumed
JZ ALTBRK_NO_ASCIIBYTE
SHIFTBRK_NONALT:
RET
;Shift key pressed here ...
SHIFTMAKE:
OR CL,AL
OR BIOS_EXTKB_SHIFT_FLAGS,CH
NEW_SHIFT_STATE:
MOV BIOS_KB_SHIFT_FLAGS,CL
NEW_SHIFT_STATE2:
AND BIOS_KB_EXTSTAT_1,NOT (LASTCODE_E0 OR LASTCODE_E1)
ALTBRK_NO_ASCIIBYTE:
MOV AH,STORE_NOCODE
RET
SHIFTKEY_HANDLER ENDP
ACK_HANDLER PROC NEAR
;---------------------------------------
;Set bit in control word that we received ACK code
;---------------------------------------
MOV AL,ACK_FROM8042
JMP SHORT KB_CMD_RX
ACK_HANDLER ENDP
RESEND_HANDLER PROC NEAR
;---------------------------------------
;Set bit in control word that we received RESEND code
;---------------------------------------
MOV AL,RESEND_FROM8042
KB_CMD_RX:
OR BIOS_KB_EXTSTAT_2,AL
AND BIOS_KB_EXTSTAT_1,NOT (LASTCODE_E0 OR LASTCODE_E1)
MOV AH,STORE_NOCODE
RET
RESEND_HANDLER ENDP
OVERRUN_HANDLER PROC NEAR
;---------------------------------------
;---------------------------------------
AND BIOS_KB_EXTSTAT_1,NOT (LASTCODE_E0 OR LASTCODE_E1)
;Fall into SYS_HANDLER since it's a dummy
; MOV AH,BEEP_NOCODE
; RET
OVERRUN_HANDLER ENDP
SYS_HANDLER PROC NEAR
;---------------------------------------
;---------------------------------------
MOV AH,BEEP_NOCODE
RET
SYS_HANDLER ENDP
;
WAIT_8042_ACCEPTED PROC NEAR
;---------------------------------------
;This routine waits until the 8042 has received the command byte
;---------------------------------------
CALL WAIT_ACCEPTED
JNZ RX_BY_8042
CLI
WAIT_ACCEPTED:
XOR CX,CX
WAIT_8042_BYTE:
IN AL,IO_KB_8042
TEST AL,_8042_IBUF_FULL
LOOPNZ WAIT_8042_BYTE
RX_BY_8042:
RET
WAIT_8042_ACCEPTED ENDP
NEW_LEDS PROC NEAR
;---------------------------------------
;Build the new LED byte and sends the commands to 8042 to have
;the indicators displayed.
;
;Entry:
; CL = BIOS_KB_SHIFT_FLAGS
;---------------------------------------
PUSH CX
CLI
BTS BIOS_KB_EXTSTAT_2,6 ;BIT 6=LEDUPD_INPROG
JC LEDS_GOOD
SHR CL,4 ;MOVE ACTIVE BITS TO LOW NYBBLE
MOV CH,(CAPSLK_LED OR NUMLK_LED OR SCRLK_LED)
AND CL,CH
PUSH CX ;SAVE INDICATORS
NOT CH
AND CH,BIOS_KB_EXTSTAT_2 ;INDICATORS OFF
OR CH,CL ;NEW INDICATORS ON
MOV BIOS_KB_EXTSTAT_2,CH ;RESAVE
STI
ENABLE_KB
MOV AH,KB_8042_NEWLED
CALL SEND_8042_COMMAND
POP CX ;RESTORE INDICATORS
JC KB_CRASHED
MOV AH,CL ;INDICATORS TO AH
CALL SEND_8042_COMMAND ;SEND THE BYTE
JNC NEW_LEDS_SET ;SUCCESSFUL
;Something WRONG with 8042 interface .. clear and re-enable
KB_CRASHED:
MOV AL,KB_8042_CLR_REENABLE
CALL SEND_8042_COMMAND
NEW_LEDS_SET:
AND BIOS_KB_EXTSTAT_2,NOT LEDUPD_INPROG ;CLEAR UPDATE FLAG
LEDS_GOOD:
STI
POP CX
RET
NEW_LEDS ENDP
SEND_8042_COMMAND PROC NEAR
;---------------------------------------
;Sends command to 8042, and waits for either ACK or RESEND
;to be received.
;
;Up to three retries will be attempted if RESEND is received.
;
;Entry:
; AH = byte to output
;
;Returns:
; CY=1 if ACK not received
; Interrupts are turned OFF on exit !
;---------------------------------------
PUSH DX
MOV DL,3
RESEND_8042_CMD:
AND BIOS_KB_EXTSTAT_2, NOT (RESEND_FROM8042 OR ACK_FROM8042)
CALL WAIT_8042_ACCEPTED
MOV AL,AH
OUT IO_KB_DATA,AL
STI
XOR CX,CX
WAIT_CMD_ACCEPT:
TEST BIOS_KB_EXTSTAT_2,(RESEND_FROM8042 OR ACK_FROM8042)
LOOPZ WAIT_CMD_ACCEPT
JZ CMD_FAILED
BTS BIOS_KB_EXTSTAT_2,4 ;BIT 4 = ACK_FROM8042
JC SEND_CMD_RET ;ACK RECEIVED, CMC WILL MAKE CY=0
CMD_FAILED: ;NO RESPONSE OR 'RESEND'
DEC DL
JNZ RESEND_8042_CMD
;ELSE DL=0, CY=0, CMC WILL MAKE 1
SEND_CMD_RET:
CMC
POP DX
RET ;CY=0 FROM 'TEST'
SEND_8042_COMMAND ENDP
IFDEF LINK_CPP_TEST
_TEXT ends
ELSE
IFDEF STANDALONE_TEST
_TEXT ends
ELSE
zcode ends
ENDIF
ENDIF
END